﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Collections;
using System.Reflection;
using System.Windows.Forms;

namespace Billing
{
    public interface IUserRightsLoader
    {
        void FillRightsFromDatabase(Object obj, UserRightsManager manager);
    }

    public class UserRightsManager
    {
        private static Dictionary<string, Hashtable> mRightProperties = new Dictionary<string, Hashtable>();
        private static IUserRightsLoader mUserRightsLoader;

        public static IUserRightsLoader UserRightsLoader
        {
            get { return mUserRightsLoader; }
            set { mUserRightsLoader = value; }
        }

        // Used for GetType().FindMembers(...)
        public static bool PropertySearchCriteria(MemberInfo objMemberInfo, Object objSearch)
        {
            PropertyInfo propertyInfo = (PropertyInfo)objMemberInfo;
            object[] Attributes = propertyInfo.GetCustomAttributes(objSearch as Type, true);

            return (Attributes.Length > 0 && propertyInfo.PropertyType == typeof(bool));
        }

        /// <summary>
        /// Setup properties in obj according to user rigths
        /// </summary>
        /// <param name="obj"></param>
        public void SetupProperties(Form obj)
        {
            if (mRightProperties == null || obj == null)
                return;
            string fullName = obj.GetType().FullName;

            // Check cache
            if (!mRightProperties.ContainsKey(fullName))
            {
                // Try to load from database
                if (mUserRightsLoader != null)
                {
                    mUserRightsLoader.FillRightsFromDatabase(obj, this);
                }

                if (!mRightProperties.ContainsKey(fullName))
                {
                    // Database do not contain right properties for this form
                    return;
                }
            }

            Hashtable formRights = mRightProperties[fullName];
            Setup(obj, formRights, typeof(RightAttribute));
            Setup(obj, formRights, typeof(RightAttributeExistence));
            //MemberInfo[] memberInfos = obj.GetType().FindMembers(MemberTypes.Property, BindingFlags.Public | BindingFlags.Instance | BindingFlags.FlattenHierarchy
            //                                                        , new MemberFilter(PropertySearchCriteria), typeof(RightAttribute));
            //foreach (MemberInfo memberInfo in memberInfos)
            //{
            //    PropertyInfo propertyInfo = (PropertyInfo)memberInfo;
            //    propertyInfo.SetValue(obj, formRights.Contains(propertyInfo.Name), null);
            //}

            //memberInfos = obj.GetType().FindMembers(MemberTypes.Property, BindingFlags.Public | BindingFlags.Instance | BindingFlags.FlattenHierarchy, new MemberFilter(PropertySearchCriteria), typeof(RightAttributeExistence));
            //foreach (MemberInfo memberInfo in memberInfos)
            //{
            //    PropertyInfo propertyInfo = (PropertyInfo)memberInfo;
            //    propertyInfo.SetValue(obj, formRights.Contains(propertyInfo.Name), null);
            //}
        }
        private void Setup(Form obj, Hashtable formRights, Type type)
        {
            MemberInfo[] memberInfos = obj.GetType().FindMembers(MemberTypes.Property, BindingFlags.Public | BindingFlags.Instance | BindingFlags.FlattenHierarchy
                                                                    , new MemberFilter(PropertySearchCriteria), type);
            foreach (MemberInfo memberInfo in memberInfos)
            {
                PropertyInfo propertyInfo = (PropertyInfo)memberInfo;
                propertyInfo.SetValue(obj, formRights.Contains(propertyInfo.Name), null);
            }
        }


        public bool GetPropertyStatus(string formPath, string propertyName)
        {
            Hashtable formProperties = mRightProperties[formPath];
            return formProperties != null && formProperties.Contains(propertyName);
        }


        public void AddObjectProperty(string fullName, string propertyName)
        {
            Hashtable hashTable = null;

            if (!mRightProperties.ContainsKey(fullName))
            {
                hashTable = new Hashtable();
                mRightProperties.Add(fullName, hashTable);
            }
            else
            {
                hashTable = mRightProperties[fullName];
            }

            hashTable[propertyName] = String.Empty;
        }

    }
}
